/*!
 * Created by ijymlee on 2017-06-22 13:31.
 */
/*
 * We send in the hash of translated strings so that Spring will have a chance
 * to resolve them with the spring:message tag.  If we put the spring:message
 * tag in this JS file, the keys would never get resolved.
 */
function strengthBar(barElement, textElement, divElement, formElement, titleElement, i18nHash) {
    var bar = barElement.progressBar({
        showText: false,
        boxImage: '//www.redhat.com/g/chrome/progressbar.gif',
        barImage: {
            0: '//www.redhat.com/g/chrome/progressbg-too-short.png',
            25: '//www.redhat.com/g/chrome/progressbg-very-weak.png',
            50: '//www.redhat.com/g/chrome/progressbg-weak.png',
            75: '//www.redhat.com/g/chrome/progressbg-good.png',
            100: '//www.redhat.com/g/chrome/progressbg-strong.png'
        }
    });

    var text = textElement;
    titleElement.css('display', 'inline');

    formElement.keyup(function() {
        var password = formElement.val();

        if (password.length === 0) {
            barElement.progressBar(0);
            textElement.detach();
        } else {
            text.appendTo(divElement);

            if (password.length < 6) {
                barElement.progressBar(5);
                text.html(i18nHash.tooShort);
            } else {
                var score = passwordCheck(password);

                if (score >= 0 && score < 25) {
                    barElement.progressBar(25);
                    text.html(i18nHash.veryWeak);
                } else if (score >= 25 && score < 50) {
                    barElement.progressBar(50);
                    text.html(i18nHash.weak);
                } else if (score >= 50 && score < 75) {
                    barElement.progressBar(75);
                    text.html(i18nHash.good);
                } else if (score >= 75 && score <= 100) {
                    barElement.progressBar(100);
                    text.html(i18nHash.strong);
                }
            }
        }
    });
}

String.prototype.reverse = function() {
    return this.split("").reverse().join("");
};

function passwordCheck(password) {
    if (!password) {
        return 0;
    }
    var upperCase = 0;
    var lowerCase = 0;
    var numbers = 0;
    var symbols = 0;
    var middleNumbers = 0;
    var middleSymbols = 0;

    var upperCaseScore = 0;
    var lowerCaseScore = 0;
    var numberScore = 0;

    var upperCaseIndex = -1;
    var consecutiveUpperCase = 0;
    var lowerCaseIndex = -1;
    var consecutiveLowerCase = 0;
    var numberIndex = -1;
    var consecutiveNumber = 0;

    var len = password.length;

    for (var i = 0; i < len; i++) {
        var letter = password[i];
        if (letter.match(/[A-Z]/g)) {
            if (upperCaseIndex >= 0 && upperCaseIndex + 1 === i) {
                consecutiveUpperCase++;
            }
            upperCaseIndex = i;
            upperCase++;
        }
        if (letter.match(/[a-z]/g)) {
            if (lowerCaseIndex >= 0 && lowerCaseIndex + 1 === i) {
                consecutiveLowerCase++;
            }
            lowerCaseIndex = i;
            lowerCase++;
        }
        if (letter.match(/[0-9]/g)) {
            if (i > 0 && i < (len - 1)) {
                middleNumbers++;
            }
            if (numberIndex >= 0 && numberIndex + 1 === i) {
                consecutiveNumber++;
            }
            numberIndex = i;
            numbers++;
        }
        if (letter.match(/[^a-zA-Z0-9_]/g)) {
            if (i > 0 && i < (len - 1)) {
                middleSymbols++;
            }
            symbols++;
        }
    }

    // 4 points for each character
    var lengthScore = (len * 4);

    // If a password is all upper case or lower case, the bonus is zero.
    // The formula below rewards variation.
    if (upperCase > 0 && upperCase < len) {
        upperCaseScore = (len - upperCase) * 2;
    }

    if (lowerCase > 0 && lowerCase < len) {
        lowerCaseScore = (len - lowerCase) * 2;
    }

    // 4 points for each number, provided the whole password isn't numbers.
    if (numbers > 0 && numbers < len) {
        numberScore = numbers * 4;
    }

    // 6 points for including a symbol
    var symbolScore = (symbols > 0) ? 6 : 0;

    // 2 points for every symbol and number contained
    // within the middle of the password
    var middleNumberAndSymbolScore = (middleNumbers + middleSymbols) * 2;

    var score = lengthScore + upperCaseScore + lowerCaseScore + numberScore + symbolScore + middleNumberAndSymbolScore;

    // Now process deductions for bad practices.

    // Subtract n points for letter only passwords
    if (lowerCase + upperCase === len) {
        score -= lowerCase + upperCase;
    }

    // Subtract n points for number only passwords
    if (numbers === len) {
        score -= numbers;
    }

    // Subtract 2 points for every upper case letter that follows an
    // upper case letter, every lower case letter that follows a lower
    // case letter, and every number that follows a number
    score -= (consecutiveNumber * 2) + (consecutiveUpperCase * 2) + (consecutiveLowerCase * 2);

    var alphaSeq = "abcdefghijklmnopqrstuvwxyz";
    // Subtract 3 points for each instance of three sequential letters
    score -= sequenceCheck(password, alphaSeq) * 3;

    var numericSeq = "01234567890";
    // Subtract 3 points for each instance of three sequential letters
    score -= sequenceCheck(password, numericSeq) * 3;

    var symbolSeq = "!@#$%^&*()";
    // Subtract 3 points for each instance of a three symbol sequence
    score -= sequenceCheck(password, symbolSeq) * 3;

    return score;
}

function sequenceCheck(password, seq) {
    var sequences = 0;
    for (var i = 0; i < (seq.length - 3); i++) {
        var forward = seq.substring(i, i + 3);
        var reverse = forward.reverse();

        if (password.toLowerCase().indexOf(forward) !== -1 || password.toLowerCase().indexOf(reverse) !== -1) {
            sequences++;
        }
    }
    return sequences;
}
